package sketch.generator;

import randoop.RMethod;
import randoop.StatementKind;
import sketch.ExecutableSequenceContent;
import sketch.MethodExecOutcome;
import sketch.SMethod;
import sketch.SketchSequence;
import sketch.ValueChoice;
import sketch.util.Checker;
import sketch.util.RandoopUtil;
import sketch.util.SketchUtil;

public class ConstructorSequenceGenerator <T extends SketchSequence> extends SingleSequenceGenerator<T> {

	//for empty construct
	public ConstructorSequenceGenerator(Class<?> clazz) {
		super(null, SMethod.constructor(clazz), ValueChoice.getMockPool());
	}
	
	//for construct with parameters
	public ConstructorSequenceGenerator(Class<?> clazz, ValueGenerator<? extends Object> generator) {
		super(null, SMethod.constructor(clazz), generator);
	}
	
	public ConstructorSequenceGenerator(Object receiver, SMethod method,
			ValueGenerator<? extends Object> generator) {
		super(receiver, method, generator);
	}
	
	@Override
	public ExecutableSequenceContent[] executables() {
		throw new UnsupportedOperationException("executables() is not supported in constructor sequence generator!");
	}
	
//	@Override
//	public Object[] evaluate() {
//		throw new UnsupportedOperationException("The evaluate method in constructor sequence is not supported!");
//	}
	
	@Override
	protected SketchSequence composeSequence() {
		String lookupMethodName = super.smethod.getMethodNames()[0];
		Checker.checkTrue(lookupMethodName.indexOf("<init>") != -1, "Not a constructor: " + lookupMethodName);
		
		StatementKind s = GenTests.lookupForStatement(this.smethod.sclazz.clazz, lookupMethodName);
		Checker.checkNull(s, "StatementKind for method: " +lookupMethodName + " in class: " + this.smethod.sclazz.clazz + " is null!");
		
		Object arg = "";
		if(RandoopUtil.getParamNum(s) != 0) {
		  if(!super.valueGenerator.hasNext()) {
			throw new IterationException("There is no more value for ValueGenerator.");
		  }
		  arg = super.valueGenerator.next();
		}
		SketchSequence sequence = new SketchSequence();
		//String method = SketchUtil.removeMethodParam(super.smethod.getMethodNames()[0]);
		
		boolean hasArgument = true;
		if(s instanceof RMethod) {
			RMethod rmethod = (RMethod)s;
			if(rmethod.getMethod().getParameterTypes().length == 0) {
				hasArgument = false;
			}
		}
		
		if(!hasArgument) {
			arg = "";
		}
		
		Class<?> clazz = this.smethod.sclazz.clazz;
		sequence.addText(clazz.getName() + " " +  SketchSequence.RECEIVER//SketchUtil.createVarName(clazz)
		  + " = new " + clazz.getName() + "(" +  arg + ");");
		
		return sequence;
	}
	
//	@Override
//	protected MethodExecOutcome[] executionResult() {
//		String lookupMethodName = super.smethod.getMethodNames()[0];
//		Checker.checkTrue(lookupMethodName.indexOf("<init>") != -1, "Not a constructor: " + lookupMethodName);
//		if(lookupMethodName.equals("<init>")) {
//			lookupMethodName = "<init>()";
//		}
//		StatementKind s = GenTests.lookupForStatement(this.smethod.sclazz.clazz, lookupMethodName);
//		Checker.checkNull(s, "StatementKind for method: " +lookupMethodName + " is null!");
//		
//		Class<?> retType = RandoopUtil.getReturnType(s);
//		if(retType.equals(void.class)) {
//			return null;
//		}
//		
//		return new MethodExecOutcome[]{new MethodExecOutcome()};
//	}
	

}
